package cn.sytton.taffecloud.gateway.filter;

import cn.sytton.taffecloud.common.base.properties.TokenProperties;
import cn.sytton.taffecloud.common.base.util.JwtUtil;
import cn.sytton.taffecloud.common.base.security.LoginUser;
import cn.sytton.taffecloud.gateway.util.WebFluxUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.PathContainer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.pattern.PathPatternParser;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

/**
 * 鉴权过滤器
 *
 * @author skyrock
 */
@Slf4j
@Component
public class AuthFilter implements GlobalFilter, Ordered {

    @Resource
    private cn.sytton.taffecloud.gateway.config.ApiConfig ApiConfig;
    @Resource
    private TokenProperties tokenProperties;
    @Resource
    private JwtUtil jwtUtil;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();

        // 允许匿名的请求直接跳过
        String url = request.getURI().getPath();
        String[] anonymousApi = ApiConfig.getAnonymousArray();
        for (String pattern : anonymousApi) {
            if (new PathPatternParser().parse(pattern).matches(PathContainer.parsePath(url))) {
                return chain.filter(exchange);
            }
        }

        String token = request.getHeaders().getFirst(tokenProperties.getHeader());
        if (!StringUtils.hasText(token)) {
            return unauthorizedResponse(exchange, "令牌不能为空");
        }
        LoginUser loginUser = jwtUtil.getLoginUser(token);
        if (loginUser == null) {
            return unauthorizedResponse(exchange, "令牌无效或已过期");
        } else {
            //延长令牌有效期
            jwtUtil.extendTime(loginUser);
            return chain.filter(exchange);
        }
    }

    private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg) {
        log.error("[认证失败]请求路径:{}", exchange.getRequest().getPath());
        return WebFluxUtil.webFluxResponseWriter(exchange.getResponse(), HttpStatus.UNAUTHORIZED, msg);
    }

    @Override
    public int getOrder() {
        return 0;
    }

}
